/*
 *
 * Copyright (c) 2007, Sun Microsystems, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *  * Neither the name of Sun Microsystems nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package ace.system.sound;

import java.io.*;
import javax.microedition.lcdui.*;
import javax.microedition.media.*;
import javax.microedition.media.control.*;


/**
 * GUI functionality for SimplePlayer.
 * This class is used by SimplePlayerCanvas and SimplePlayerForm and
 * provides the actual logic.
 * SimplePlayerCanvas and SimplePlayerForm provide the interaction of
 * the main window with the user.
 *
 * @version 1.10
 */
public class SimplePlayer implements PlayerListener, ItemStateListener {
    // loop
    public static final int LOOP_ONCE = 0;
    public static final int LOOP_3    = 1;
    public static final int LOOP_INF  = 2;
    protected int loopmode = LOOP_ONCE;

    // the player instance
    protected Player player=null;
	protected boolean isMute;

    // song descriptors
    protected String title;
    protected InputStream songInputStream;
    protected String songContentType="";
    protected String songLocator="";
    protected String songName="";
    protected String[] songDisplayNames = new String[0];

    // /////////////////////////// INITIALIZATION /////////////////////////////

    /** Note: parent MUST be Displayable */
    public SimplePlayer() {
		isMute = false;
		initialize("SimplePlayer");
    }

    private void initialize(String title) {
		this.title = title;
		initialize();
    }

    private void initialize() {
		setSong("No song loaded", "");
    }

    public void setSong(String name, String locator) {
		songLocator = locator;
		songInputStream = null;
		songContentType = "";
		doSetSong(name);
    }

	public void setSong(String locator, String contentType, int loop){
		songLocator = locator;
		songInputStream = getClass().getResourceAsStream(locator);
		songContentType = contentType;
		loopmode = loop;
		doSetSong("default");
	}

    private void doSetSong(String name) {
		songName = name;
		songDisplayNames = new String[1];
		songDisplayNames[0] = name;
		
		closePlayer();
    }

    // /////////////////////////// VISUAL FEEDBACK ////////////////////////////
    private void updateVolume(VolumeControl c) {
		if (c==null) {
			c = getVolumeControl();
		}
		
		if (c != null) {
			c.setMute(isMute);
		}
    }

    private void updateLoop() {
		if (player != null) {
			try {
				int loop=1;
				switch (loopmode) {
					case LOOP_ONCE:
						loop=1;
						break;
					case LOOP_3:
						loop=3;
						break;
					case LOOP_INF:
						loop=-1;
						break;
				}
				
				boolean restart = false;
				if (player.getState() == player.STARTED) {
					player.stop();
					restart = true;
				}

				player.setLoopCount(loop);
				if (restart) {
					player.start();
				}
			} catch (Exception e) {}
		}
    }

    // /////////////////////////// CONTROLS ///////////////////////////////////
    public Control[] getControls() {
		try {
			if (player != null) {
				return player.getControls();
			}
		} catch (IllegalStateException ise) {
			// thrown when player is closed
		}
		return null;
    }

    private VolumeControl getVolumeControl() {
		try {
			if (player != null) {
				return (VolumeControl) player.getControl("VolumeControl");
			}
		} catch (IllegalStateException ise) {
			// thrown when player is closed
		}
		return null;
    }

    // /////////////////////////// PLAYBACK CONTROL ///////////////////////////
    private void assertPlayer() throws Throwable {
		try {
			if (player == null) {
				if (songInputStream == null) {
					player = Manager.createPlayer(songLocator);
				} else {
					player = Manager.createPlayer(songInputStream, songContentType);
				}
			}
			
			player.addPlayerListener(this);
			player.realize();
			player.prefetch();

			VolumeControl vc = getVolumeControl();
			if(vc != null){
				vc.setLevel(50);
			}
			
			updateVolume(null);
			updateLoop();
		} catch (Throwable t) {
			player=null;
		}
    }


    public void startPlayer() {
		if(isMute) return;
		try {
			if (player == null || player.getState() < Player.PREFETCHED) {
				assertPlayer();
			}
			
			if (player == null || player.getState() >= Player.STARTED) {
				return;
			}

			player.start();
		} catch (Throwable t) {}
    }

    public void closePlayer() {
		if (player != null) {
			try {
				player.stop();
			} catch (Exception e) {}

			player.close();
			player = null;
		}
    }


    public void pausePlayer() {
		if (player != null) {
			try {
				player.stop();
			} catch (Exception e) {}
		}
    }

    public void togglePlayer() {
		if (player!=null) {
			if (player.getState() == Player.STARTED) {
				pausePlayer();
			} else {
				startPlayer();
			}
		}
    }

    public void changeVolume(boolean decrease) {
		int diff = 10;
		if (decrease) {
			diff = -diff;
		}
		
		VolumeControl vc = getVolumeControl();
		if (vc != null) {
			int cv = vc.getLevel();
			cv += diff;
			vc.setLevel(cv);
			updateVolume(vc);
		}
    }

    public void toggleMute() {
		isMute = !isMute;
		VolumeControl vc = getVolumeControl();
		if (vc != null) {
			vc.setMute(!vc.isMuted());
			updateVolume(vc);
		}

		if(isMute)	pausePlayer();
		else		startPlayer();
    }

	public void setMute(boolean mute){
		isMute = mute;
		VolumeControl vc = getVolumeControl();
		if (vc != null) {
			vc.setMute(mute);
			updateVolume(vc);
		}

		if(mute)	pausePlayer();
		else		startPlayer();
	}

    public void playerUpdate(Player plyr, String evt, Object evtData) {
		try {
			if (evt == END_OF_MEDIA && plyr.getState() == Player.STARTED) {
				return;
			}
		} catch (Throwable t) {}
    }

    public void itemStateChanged(Item item) {
		if (item!=null) {
			VolumeControl vc = getVolumeControl();
			if (vc != null) {
				updateVolume(vc);
			}
		}
    }
}
